package main

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
)

func f1(filePath string) {
	f, _ := os.OpenFile(filePath, os.O_RDWR, 0644)
	defer func() {
		_ = f.Close()
	}()

	// 移动文件指针位置
	_, _ = f.Seek(0, 0)

	// 从指定位置读取 16 个字节
	var buf [8]byte
	n, err := f.Read(buf[:])
	if err != nil && err != io.EOF {
		fmt.Println(err)
		return
	}

	fmt.Println(string(buf[:n]))

	fInfo, _ := f.Stat()
	// 移动到指定位置
	_, _ = f.Seek(fInfo.Size(), 0)

	// 并写入数据
	_, _ = f.Write([]byte("\n读写文件\n"))
}

func f2(filePath string) {
	f, err := os.OpenFile(filePath, os.O_RDWR, 0644)
	// 不能直接对源文件直接进行插入操作, 故 需要借助临时文件
	tmpFileName := "./file.tmp"
	absTmpFilePath, _ := filepath.Abs(filepath.Join(os.TempDir(), tmpFileName))
	defer func() {
		_ = f.Close()
		// 重命名临时文件 以 覆盖源文件
		fmt.Printf("保存文件 %s => %s", absTmpFilePath, filePath)
		_ = os.Rename(absTmpFilePath, filePath)
	}()
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Printf("打开 临时文件: %s\n", absTmpFilePath)
	tmp, err := os.OpenFile(absTmpFilePath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0644)
	defer func() {
		_ = tmp.Close()
	}()
	if err != nil {
		fmt.Println(err)
		return
	}

	// 重置文件指针
	_, _ = f.Seek(0, 0)
	_, _ = tmp.Seek(0, 0)

	// 从源文件读取 n 个字节
	var buf [8]byte
	n, err := f.Read(buf[:])
	if err != nil {
		fmt.Println(err)
		return
	}
	// 并写入临时文件
	_, _ = tmp.Write(buf[:n])
	// 写入 插入的内容
	tmpContent := "\n==-->插入的内容<--=="
	_, _ = tmp.Write([]byte(tmpContent))

	// 再把源文件后续的内容写入
	for {
		var tmpBuf [1024]byte
		n, err = f.Read(tmpBuf[:])
		if err != nil {
			if err == io.EOF {
				break
			}
			fmt.Println(err)
			return
		}
		_, _ = tmp.Write(tmpBuf[:n])
	}
}

func main() {
	fileName := "./test.file"
	// os.TempDir() 获取 系统 临时目录
	absPath, _ := filepath.Abs(filepath.Join(os.TempDir(), fileName))
	fmt.Println("打开文件", absPath)
	f1(absPath)

	fmt.Println("=========================================================")

	f2(absPath)
}
